package net.tensor.skynet.fragment

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Rect
import android.os.Build
import android.os.Bundle
import android.view.View
import android.view.animation.Animation
import android.view.animation.AnimationUtils
import android.widget.AdapterView
import android.widget.ArrayAdapter
import androidx.annotation.RequiresApi
import androidx.core.os.bundleOf
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.gson.Gson
import kotlinx.android.synthetic.main.fragment_list.*
import kotlinx.android.synthetic.main.include_toolbar.*
import kotlinx.coroutines.*
import net.tensor.skynet.R
import net.tensor.skynet.adapter.CardAdapter
import net.tensor.skynet.adapter.SkynetAdapter
import net.tensor.skynet.common.user.entity.User
import net.tensor.skynet.entity.DataContainer
import net.tensor.skynet.entity.Model
import net.tensor.skynet.service.UserService
import net.tensor.skynet.utils.BaseUtils
import okhttp3.OkHttpClient
import java.io.InputStream
import java.util.*
import javax.net.ssl.SSLContext
import javax.net.ssl.X509TrustManager
import kotlin.coroutines.CoroutineContext

class ListDemoFragment : Fragment(R.layout.fragment_list), CoroutineScope {

    /**
     * job用于控制协程,后面launch{}启动的协程,
     * 返回的job就是这个job对象
     */
    private lateinit var selected: Model
    private lateinit var job: Job
    private var baseUtils: BaseUtils? = null
    private var adapter: SkynetAdapter? = null

    /**
     * Https网络相关变量
     */
    private var stream: InputStream? = null
    private var trustManager: X509TrustManager? = null
    private var sslContext: SSLContext? = null
    private var okHttpClient: OkHttpClient? = null
    private var gson: Gson? = null
    private var retrofit: UserService? = null

    /**
     * 当acitivity结束之后,我们不需要再请求网络了,结束当前协程
     */
    override fun onDestroy() {
        super.onDestroy()
        job.cancel()
    }

    /**
     * 继承CoroutineScope必须初始化coroutineContext变量
     * 这个是标准写法,+其实是plus方法前面表示job,用于控制协程,
     * 后面是Dispatchers,指定启动的线程
     * 协程上下文
     */
    override val coroutineContext: CoroutineContext
        get() = job + Dispatchers.Main

    /**
     * 初始化网络
     */
    private fun initNetwork() {
        job = Job()
        baseUtils = BaseUtils()
        trustManager = baseUtils!!.getTrustManager(this.resources.openRawResource(R.raw.server200))
        sslContext = trustManager?.let { baseUtils!!.getSSLContext(it) }
        okHttpClient =
            sslContext?.let { trustManager?.let { it1 -> baseUtils!!.getOkHttpClient(it1, it) } }
        gson = baseUtils!!.getGson()
        retrofit = okHttpClient?.let {
            baseUtils!!.getRetrofit(
                it,
                "https://192.168.1.200:9999",
                gson ?: Gson()
            )
        }
    }

    /**
     * 创建视图时
     */
    @RequiresApi(Build.VERSION_CODES.M)
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        recyclerView.adapter = CardAdapter()
        recyclerView.layoutManager = LinearLayoutManager(context)
        //添加加载下一页监听
        reloadButton.setOnClickListener {
            getData(
                DataContainer.pageNum + 1,
                DataContainer.pageSize
            )
        }
        //启动recyclerView
        setupRecyclerView()
        //启动微调器---调整布局动画
        setupSpinner()
        //运行布局动画
        runLayoutAnimation(selected)
        //获取数据
        //初始化网络
        initNetwork()
        //从网络获取数据
        getData(0, 10)
        //传递参数到详情页面
    }

    /**
     * 启动 RecyclerView
     */
    private fun setupRecyclerView() = recyclerView.apply {
        addItemDecoration(ItemOffsetDecoration(context))
    }

    /**
     * 获取网络数据
     */
    private fun getData(page: Int, pageSize: Int) {
        launch {
            try {
                val map = mutableMapOf<String, Int>()
                map["page"] = page
                map["pageSize"] = pageSize
                val result = withContext(Dispatchers.IO) {
                    retrofit?.queryPage(
                        map
                    )?.execute()
                }
                if (result != null) {
                    if (result.isSuccessful) {
                        DataContainer.pageNum = result.body()?.pageNum ?: 0
                        DataContainer.pageSize = result.body()?.pageSize ?: 0
                        DataContainer.pages = result.body()?.pages ?: 0
                        DataContainer.total = result.body()?.total ?: 0
                        DataContainer.USER_ITEMS = result.body()?.list as ArrayList<User>
                        //启动微调器
                        setupSpinner()
                        //运行布局动画
                        runLayoutAnimation(selected)
                    }
                }
            } catch (e: Exception) {
            }
        }
    }

    /**
     * 设置微调器
     */
    @SuppressLint("ResourceType")
    private fun setupSpinner() = spinner.apply {
        val animations = Model(
            R.string.animation_slide_from_right,
            R.anim.layout_animation_from_right
        )
        selected = Model(
            R.string.animation_slide_from_right,
            R.anim.layout_animation_from_right
        )
        adapter = ArrayAdapter<Any?>(
            context,
            R.layout.row_spinner_item,
            animations.resourceId
        )
        onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
            override fun onItemSelected(adapterView: AdapterView<*>, view: View?, i: Int, l: Long) {
                selected = animations.also { runLayoutAnimation(it) }
            }

            override fun onNothingSelected(adapterView: AdapterView<*>?) = Unit
        }
    }

    /**
     * 运行布局动画
     */
    private fun runLayoutAnimation(model: Model) = recyclerView.apply {
        layoutAnimation = AnimationUtils.loadLayoutAnimation(context, model.resourceId)
        adapter?.notifyDataSetChanged()
        scheduleLayoutAnimation()

        layoutAnimationListener = object : Animation.AnimationListener {
            override fun onAnimationStart(animation: Animation?) {
                layoutManager?.findViewByPosition(0)?.clearAnimation()
            }

            override fun onAnimationEnd(animation: Animation?) = Unit
            override fun onAnimationRepeat(animation: Animation?) = Unit
        }
    }

    /**
     * 伴侣对象
     */
    companion object {
        const val ARG_ITEM_ID = "ARG_ITEM_ID"
        private const val ARG_WITH_HEADER = "arg_with_header"
        fun instance() = ListDemoFragment()
            .apply {
                arguments = bundleOf()
            }
    }
}

/**
 * 物品偏移装饰
 */
private class ItemOffsetDecoration(
    context: Context
) : RecyclerView.ItemDecoration() {
    private val spacing = context.resources.getDimensionPixelOffset(R.dimen.default_spacing_medium)
    override fun getItemOffsets(
        outRect: Rect,
        view: View,
        parent: RecyclerView,
        state: RecyclerView.State
    ) {
        val adapter = parent.adapter ?: return
        val vh = parent.findContainingViewHolder(view) ?: return
        val isFirst = vh.adapterPosition == 0
        val isLast = vh.adapterPosition == adapter.itemCount - 1
        when {
            isFirst -> outRect.set(spacing, spacing / 2, spacing, spacing / 2)
            isLast -> outRect.set(spacing, spacing / 2, spacing, spacing)
            else -> outRect.set(spacing, spacing / 2, spacing, spacing / 2)
        }
    }
}